Skip to content

docs: client integration guide, admission-control scope, and README client library - #21

Merged
zippy merged 3 commits into
feat/worker-kv-parityfrom
docs/client-integration
Aug 21, 2026
Merged

zippy merged 3 commits into
feat/worker-kv-parityfrom
docs/client-integration

Conversation

@zippy

@zippy zippy commented Aug 18, 2026

Copy link
Copy Markdown
Member

Documentation only — no behavior changes. Stacks on the multi-network PR (merge that first); it documents the session-recovery reconnect that PR adds.

There was no client-integration documentation anywhere: JOINING_SERVICE_API.md documents each endpoint in isolation and its example flows are all happy paths from a clean slate, and the README never mentioned JoiningClient. An app developer embedding the client had nothing telling them what to call on startup.

  • New JOINING_SERVICE_API.md §4 "Client Integration" — the startup decision tree, decided entirely by local state: hApp installed → nothing to do; no agent key → generate and join; agent key present but hApp not installed → reconnect first, and only fall through to join on 403 agent_not_joined. Reconnect goes first because it needs only the key and a signature, while join may need claims, an invite code, or an interactive prompt — so a crashed install recovers silently and auth is surfaced only when the agent genuinely has to join something new. Also states, normatively, that clients persist the agent-key→hApp association before calling /v1/join: local-write-before-remote-call is orderable, the reverse is not, and getting it wrong burns an invite code (fatal with single-use codes).
  • Security Considerations (§7) gains a scope statement: the service does admission control and does not prevent source-chain forks — anyone holding the private key can copy the whole conductor directory, so fork prevention is Holochain's job via validation and warrants. The 409 agent_already_joined is defended on its actual grounds (join requires no proof of key possession; the session token is a bearer credential for provision) rather than as a fork guard. Recorded so the "just make join idempotent" argument doesn't need re-litigating each time someone hits the 409.
  • Reconnect replay window documented in the same section: the signed payload is the timestamp alone (default 300s tolerance) and ready sessions never expire, so a captured request replayed inside the window yields a session token, and that token stays usable indefinitely. Widening the signed payload to cover the agent key and a server-issued nonce is the durable fix — worth its own issue.
  • New example flow for recovery after an interrupted install, and a README client-library section covering discovery, join, provision, and recovery with a typed startup example.

Two pre-existing inaccuracies fixed while in here: the security section claimed session expiry times that don't match the stores (ready sessions never expire; pending TTL default is 86400s), and one example flow showed a linker_urls_expire_at field that doesn't exist (real shape is per-entry expires_at).

Sections 4–9 renumber to 5–10 to make room for the new section; every cross-reference was audited (one moved reference updated, plus the src/types.ts header comment that names the types section — the only non-doc line in this PR).

zippy added 3 commits August 17, 2026 16:03
Adds a "Client Integration" section covering the decision a client makes
on startup -- which endpoint to call given whether an agent key exists and
whether the hApp is installed -- why reconnect goes first (both orders are
safe, so it is about what each request needs from the caller: reconnect a key
and a signature, join possibly claims and a user prompt), and the requirement
to record the agent-key-to-hApp association locally before calling /v1/join.
The Overview's flow summary gains the matching recovery stanza.

It lands as section 4, so the sections after it are renumbered: Error Response
Format 4->5, CORS and Rate Limiting 5->6, Security Considerations 6->7,
Authentication Methods Reference 7->8, Example Flows 8->9 (and its 8.x
subsections to 9.x), TypeScript Type Definitions 9->10. Two cross-references
name a moved section and are updated: auth methods in the /v1/info field table,
and the src/types.ts header comment pointing at the type definitions.
References to 3.x subsections are unaffected.

Also adds example flow 9.10, recovery after an interrupted install, and
corrects flow 9.5's reconnect response, which named a `linker_urls_expire_at`
field the service does not return -- expiry is per linker_urls entry.
Security Considerations now states what the service does and does not do:
admission control, not fork prevention. A key holder can copy the conductor
directory and fork without ever calling the service; that is Holochain's
problem, handled by validation and warrants. Records why the 409 stays as it
is -- /v1/join has no proof of key possession, so an idempotent join would
turn a public agent key into a provisioning credential and skip auth
evaluation.

Adds the reconnect replay window: the signed payload is the timestamp alone
within a configurable tolerance (default 300s) and ready sessions do not
expire, so an observed request replayed inside the window returns the session
token. Notes the available mitigations and that signing over the agent key
plus a nonce is the durable fix.

Also corrects the session-expiry bullet, which claimed 1 hour pending / 24
hours ready; the stores never expire ready sessions and pending sessions use
session.pending_ttl_seconds (default 24 hours).
Covers JoiningClient: constructing one, choosing a network, driving the
join/verify/provision flow, and the crash-recovery path via reconnect.

Both construction paths get their own example rather than one worked
example plus a prose aside, since which one applies is decided by whether
the app domain publishes a well-known document, not by preference -- and
the choice determines whether join() can route to a network on its own.
The three forms of join()'s network argument are likewise shown as three
calls instead of described as one three-way parameter.

Provision handling branches on what is present instead of assuming a
shape. Every field is optional and which ones arrive is a property of the
deployment: a membrane-proof-only or gateway-only service returns no
linker_urls at all, and /v1/info omits linker_info to match, so an absent
linker is the normal case for those deployments rather than an error.
@zippy
zippy requested a review from zo-el August 18, 2026 15:42
@zippy
zippy merged commit 3b978a7 into feat/worker-kv-parity Aug 21, 2026
1 check passed
@zippy
zippy deleted the docs/client-integration branch August 21, 2026 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants